/**
 * 
 */
package it.uniroma3.dia.digraph.algorithm.kouterplanar.kouterplanar;

import java.util.HashMap;
import java.util.InputMismatchException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.graphdrawing.graphml.xmlns.GraphType;

import it.uniroma3.dia.digraph.algorithm.Algorithm;
import it.uniroma3.dia.digraph.view.Finestrella;
import it.uniroma3.dia.digraph.view.interpolation.Interpolator;
import it.uniroma3.dia.digraph.view.interpolation.impl.Bar;

/**
 * @author Cionzo
 *
 */
public class Prova extends Algorithm {

    private KouterplanarGraph oSource;
    private Map<String, KouterplanarNode> oTargetNodemap;
    private KouterplanarGraph oTarget;
    private KouterplanarGraph targetGraph;

    /* (non-Javadoc)
     * @see it.uniroma3.dia.digraph.algorithm.Algorithm#apply(org.graphdrawing.graphml.xmlns.GraphType[])
     */
    @Override
    public void apply(GraphType... inputGraphs) {
	
	
	
	
	KouterplanarNode targetNode;
	List<KouterplanarNode> nodes;
	nodes = this.oSource.getDepth2nodes().get(0);
	for (KouterplanarNode n : nodes) {
	    n.setArrived(true);
	    n.getNode().setDefault(false);
	}
//	this.moveToBarycenter();	
//	this.updateNodeLocations();
//	this.updateView();System.out.println("XXX");Finestrella.getChar();
	
	for (int k=0;k<5;k++) {
	    this.moveToBarycenter();
	    this.moveToBarycenter(this.oTarget);
	    this.updateNodeLocations();
	    this.updateView();System.out.println(k);
	}
	
	System.out.println("source -> baycenter");Finestrella.getChar();
	
	this.moveToTargetCombination();
	this.updateNodeLocations();	
	this.updateView();
	System.out.println("target -> baycenter");Finestrella.getChar();
	
	for (int i=1;i<this.oSource.getDepth2nodes().size() && false;i++) {
	    nodes = this.oSource.getDepth2nodes().get(i);
	  //for each node at current level
	    for (KouterplanarNode current : nodes) {
		//get corresponding node on target drawing
		targetNode = this.oTargetNodemap.get(current.getNode().getId());
//		double x = 0;
//		for (Double l : current.getParent2lambda().values()) {
//		    x+=l;
//		    if (l<=0 || l>=1) {
//			System.err.println(l);
//		    }
//		}
//		    
//		System.out.print(current+" "+x+" ");
//		System.out.println(current.getParent2lambda());//TODO:debug
		
		
		//move the current node to its target location
		current.setX(targetNode.getNode().getX());
		current.setY(targetNode.getNode().getY());
		current.setArrived(true);
		current.getNode().setDefault(false);
		//update remaining nodes
		this.updateNodeLocations();		
		
		//update the view
		this.updateView();
//		current.getNode().setDefault(true);
		
		
	    }
	}
	
	this.moveToTarget();
	this.updateNodeLocations();
	this.view.update(this.targetGraph.getGraph());
//	this.updateView();
	System.out.println("target"); Finestrella.getChar();
	
	
//	//for each level from outer to inner
//	for (List<KouterplanarNode> nodes : this.oSource.getDepth2nodes().values()) {
//	    
//	    //for each node at current level
//	    for (KouterplanarNode current : nodes) {
//		//get corrisponding node on target drawing
//		targetNode = this.oTargetNodemap.get(current.getNode().getId());
//		
//		//move the current node to its target location
//		current.setX(targetNode.getNode().getX());
//		current.setY(targetNode.getNode().getY());
//		current.setArrived(true);
//		
//		//update remaining nodes
//		this.updateNodeLocations();		
//		
//		//update the view
//		this.updateView();
//		
//		
//	    }
//	}
    }
    

    /**
     * 
     */
    private void moveToBarycenter() {
	for (KouterplanarNode kn : this.oSource.getkNodeMap().values()) {
	    int n = kn.getParent2lambda().size();
	    double l = 1.0/n;
	    Map<KouterplanarNode,Double> np2l = new HashMap<KouterplanarNode, Double>();
	    
	    for (KouterplanarNode p : kn.getParent2lambda().keySet())
		np2l.put(p, l);
	    
	    kn.setParent2lambda(np2l);
	}
    }
    
    private void moveToBarycenter(KouterplanarGraph g) {
	for (KouterplanarNode kn : g.getkNodeMap().values()) {
	    int n = kn.getParent2lambda().size();
	    double l = 1.0/n;
	    Map<KouterplanarNode,Double> np2l = new HashMap<KouterplanarNode, Double>();
	    
	    for (KouterplanarNode p : kn.getParent2lambda().keySet())
		np2l.put(p, l);
	    
	    kn.setParent2lambda(np2l);
	}
    }

    /**
     * 
     */
    private void moveToTargetCombination() {
	KouterplanarNode s,t;
	Map<KouterplanarNode, Double> np2l;
	for (String sId : this.targetGraph.getkNodeMap().keySet()) {
	    s = this.oSource.getkNodeMap().get(sId);
	    t = oTargetNodemap.get(sId);
	    np2l = new HashMap<KouterplanarNode, Double>();
	    for (KouterplanarNode parent : s.getParent2lambda().keySet()) {
		np2l.put(parent, t.getParent2lambda().get(parent));
	    }
	    s.setParent2lambda(np2l);
//	    s.setX(t.getNode().getX());
//	    s.setY(t.getNode().getY());
	    
	}
    }
    private void moveToTarget() {
	KouterplanarNode s,t;
	Map<KouterplanarNode, Double> np2l;
	for (String sId : this.targetGraph.getkNodeMap().keySet()) {
	    s = this.oSource.getkNodeMap().get(sId);
	    t = this.targetGraph.getkNodeMap().get(sId);
	    np2l = new HashMap<KouterplanarNode, Double>();
	    for (KouterplanarNode parent : s.getParent2lambda().keySet()) {
		np2l.put(parent, t.getParent2lambda().get(parent));
	    }
	    s.setParent2lambda(np2l);
//	    s.setX(t.getNode().getX());
//	    s.setY(t.getNode().getY());
	    
	}
    }

    /**
     * 
     */
    private void updateNodeLocations() {
	for (List<KouterplanarNode> level : this.oSource.getDepth2nodes().values())
	    for (KouterplanarNode current : level) {
		current.getX();
		current.getY();
	    }
    }

    /* (non-Javadoc)
     * @see it.uniroma3.dia.digraph.algorithm.Algorithm#checkInput(org.graphdrawing.graphml.xmlns.GraphType[])
     */
    @Override
    public void checkInput(GraphType[] inputGraphs)
	    throws InputMismatchException {
	if (inputGraphs.length!=3)
	    throw new InputMismatchException("input size must be 3: source and target graph");
    }

    /* (non-Javadoc)
     * @see it.uniroma3.dia.digraph.algorithm.Algorithm#init(org.graphdrawing.graphml.xmlns.GraphType[])
     */
    @Override
    protected void init(GraphType... inputGraphs) {
	
	this.setoSource(new KouterplanarGraph(inputGraphs[0]));	
	this.oTarget = (new KouterplanarGraph(inputGraphs[1]));
	this.setoTargetNodemap((new KouterplanarGraph(inputGraphs[1])).getkNodeMap());
//	this.targetGraph=(new KouterplanarGraph(inputGraphs[3]));
	this.targetGraph=(new KouterplanarGraph(inputGraphs[2]));
    }

    /**
     * @param oSource the oSource to set
     */
    public void setoSource(KouterplanarGraph oSource) {
	this.oSource = oSource;
    }

    /**
     * @return the oSource
     */
    public KouterplanarGraph getoSource() {
	return oSource;
    }

    /**
     * @param oTargetNodemap the oTargetNodemap to set
     */
    public void setoTargetNodemap(Map<String, KouterplanarNode> oTargetNodemap) {
	this.oTargetNodemap = oTargetNodemap;
    }

    /**
     * @return the oTargetNodemap
     */
    public Map<String, KouterplanarNode> getoTargetNodemap() {
	return oTargetNodemap;
    }

}
